﻿namespace Resharper.Abstractions.CodeDom.TypeMembers.Methods
{
  using JetBrains.Annotations;
  using JetBrains.ReSharper.Psi;
  using JetBrains.ReSharper.Psi.Tree;
  using JetBrains.ReSharper.Psi.Util;
  using Resharper.Abstractions.CodeDom.TreeNodes;

  /// <summary>Defines the <see cref="Parameter"/> class.</summary>
  public class Parameter : TreeNode
  {
    #region Constructors and Destructors

    /// <summary>Initializes a new instance of the <see cref="Parameter"/> class.</summary>
    /// <param name="parameter">The parameter.</param>
    internal Parameter(IParameterDeclaration parameter) : base(parameter)
    {
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets the access right.
    /// </summary>
    public CodeDom.AccessRights AccessRights
    {
      get
      {
        return AccessRightsHelper.GetAccessRights(this.InternalParameter.DeclaredElement as IAccessRightsOwner);
      }
    }

    /// <summary>
    /// Gets a value indicating whether this <see cref="Parameter"/> is kind.
    /// </summary>
    public bool IsOut
    {
      get
      {
        var declaredElement = this.InternalParameter.DeclaredElement;
        if (declaredElement == null)
        {
          return false;
        }

        return declaredElement.Kind == ParameterKind.OUTPUT;
      }
    }

    /// <summary>
    /// Gets a value indicating whether this instance is ref.
    /// </summary>
    public bool IsRef
    {
      get
      {
        var declaredElement = this.InternalParameter.DeclaredElement;
        if (declaredElement == null)
        {
          return false;
        }

        return declaredElement.Kind == ParameterKind.REFERENCE;
      }
    }

    /// <summary>
    /// Gets the type.
    /// </summary>
    public bool IsReferenceType
    {
      get
      {
        var type = this.InternalParameter.Type;

        return type != null && type.IsReferenceType();
      }
    }

    /// <summary>
    /// Gets the name.
    /// </summary>
    [NotNull]
    public string Name
    {
      get
      {
        return this.InternalParameter.DeclaredName ?? string.Empty;
      }
    }

    /// <summary>
    /// Gets the internal parameter.
    /// </summary>
    [NotNull]
    internal IParameterDeclaration InternalParameter
    {
      get
      {
        return (IParameterDeclaration)this.InternalTreeNode;
      }
    }

    #endregion
  }
}